package com.code2roc.fastboot.system.org.bizlogic;

import com.code2roc.fastboot.system.enums.CommonEnum;
import com.code2roc.fastboot.system.org.model.SystemRoleDO;
import com.code2roc.fastboot.system.org.model.SystemRoleSettingDO;
import com.code2roc.fastboot.system.org.model.SystemUserDO;
import com.code2roc.fastboot.system.org.service.ISystemRoleService;
import com.code2roc.fastboot.system.org.service.ISystemRoleSettingService;
import com.code2roc.fastboot.system.org.service.ISystemUserService;
import com.code2roc.fastboot.system.setting.bizlogic.ConfigLogic;
import com.code2roc.fastboot.system.setting.model.SystemConfigDO;
import com.code2roc.fastboot.system.setting.service.ISystemMenuSettingService;
import com.code2roc.fastboot.model.BaseBootLogic;
import com.code2roc.fastboot.util.BootUtil;
import com.code2roc.fastboot.framework.util.CopyUtil;
import com.code2roc.fastboot.framework.util.*;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class UserLogic extends BaseBootLogic {
    @Autowired
    private ISystemUserService service;
    @Autowired
    private ISystemRoleService roleService;
    @Autowired
    private ISystemRoleSettingService roleSettingService;
    @Autowired
    private ISystemMenuSettingService menuSettingService;
    @Autowired
    private ConfigLogic configLogic;

    public void insert(SystemUserDO entity) throws Exception {
        if(StringUtil.isEmpty(entity.getPassword())){
            SystemConfigDO configDO = configLogic.getConfigByName("InitPWD");
            entity.setPassword(EncryptUtil.encryptByMD5(entity.getLogin_name() + "|" + configDO.getConfig_value()));
        }
        service.insert(entity);
    }

    public void delete(String row_id) {
        service.delete(row_id);
        menuSettingService.deleteSettingBySettingID(row_id);
        roleSettingService.deleteByUserID(row_id);
    }

    public void update(SystemUserDO entity) {
        service.update(entity);
        authUtil.refreshTokenInfo();
    }

    public SystemUserDO detail(String row_id) {
        List<SystemRoleDO> roleDOList = roleService.selectAllList();
        List<SystemRoleSettingDO> roleSettingDOList = roleSettingService.selectAllList();
        SystemUserDO entity = service.selectOne(row_id);
        entity.setRoleList(getUserRoleList(row_id, roleDOList, roleSettingDOList));
        return entity;
    }

    public void initPassword(String row_id) throws Exception {
        SystemUserDO entity = service.selectOne(row_id);
        SystemConfigDO configDO = configLogic.getConfigByName("InitPWD");
        entity.setPassword(EncryptUtil.encryptByMD5(entity.getLogin_name() + "|" + configDO.getConfig_value()));
        service.update(entity);
    }

    public void changePassword(String row_id, String newPassword) {
        SystemUserDO entity = service.selectOne(row_id);
        entity.setPassword(newPassword);
        service.update(entity);
    }

    public void changeStatus(String row_id) {
        SystemUserDO entity = service.selectOne(row_id);
        if (entity.getUser_status() == CommonEnum.EnableOrDisable.Enable.get_value()) {
            entity.setUser_status(CommonEnum.EnableOrDisable.Disable.get_value());
        } else {
            entity.setUser_status(CommonEnum.EnableOrDisable.Enable.get_value());
        }
        service.update(entity);
    }

    public List<SystemRoleDO> getUserRoleList(String user_id, List<SystemRoleDO> roleDOList, List<SystemRoleSettingDO> roleSettingDOList) {
        List<SystemRoleSettingDO> settingDOList = roleSettingDOList.stream().filter((SystemRoleSettingDO f) -> f.getUser_id().equals(user_id)).collect(Collectors.toList());
        List<SystemRoleDO> allRoleListCopy = CopyUtil.deepCopyList(roleDOList);
        for (SystemRoleDO roleDO : allRoleListCopy) {
            List<SystemRoleSettingDO> realitonfilter = settingDOList.stream().filter((SystemRoleSettingDO f) -> f.getRole_id().equals(roleDO.getRow_id())).collect(Collectors.toList());
            if (realitonfilter.size() > 0) {
                roleDO.setRegist(true);
            } else {
                roleDO.setRegist(false);
            }
        }
        return allRoleListCopy;
    }

    public String exportData(List<String> userIDList) {
        String fileid = "";
        try {
            DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            Calendar calendar = Calendar.getInstance();
            String dateName = df.format(calendar.getTime());
            fileid = "UserExport_" + dateName + CommonUtil.getNewGuid();
            String filename = fileid + ".xml";
            String filefullpath = "tempfiles/export/" + filename;
            FileUtil.initfloderPath("tempfiles/export/");
            Document doc = DocumentHelper.createDocument();
            Element root = doc.addElement("orgfile");
            Element filetype = root.addElement("filetype");
            filetype.setText("user");

            Element userlist = root.addElement("userlist");
            for (String userID : userIDList) {
                SystemUserDO userDO = detail(userID);
                Element user = userlist.addElement("user");
                for (Field field : userDO.getClass().getDeclaredFields()) {
                    if (!Modifier.isStatic(field.getModifiers())) {
                        field.setAccessible(true);
                        Element tablefield = user.addElement(field.getName());
                        tablefield.setText(String.valueOf(field.get(userDO)));
                    }
                }
            }

            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");
            FileOutputStream out;
            out = new FileOutputStream(filefullpath);
            XMLWriter writer = new XMLWriter(out, format);
            writer.write(doc);
            writer.close();

            StringBuilder builder = new StringBuilder();
            builder.append("导出人员信息成功！" + CommonUtil.getNewLine());
            LogUtil.writeLog("org/user", "log", builder.toString());
        } catch (Exception e) {
            e.printStackTrace();
            StringBuilder builder = new StringBuilder();
            builder.append("导出人员信息失败！" + CommonUtil.getNewLine());
            builder.append("失败异常信息:" + CommonUtil.getNewLine());
            builder.append(e.getMessage() + CommonUtil.getNewLine());
            builder.append("失败堆栈信息:" + CommonUtil.getNewLine());
            builder.append(e.getStackTrace());
            LogUtil.writeLog("org/user", "log", builder.toString());
        }
        return fileid;
    }

    @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.READ_UNCOMMITTED)
    public String importData(InputStream stream) {
        String errormsg = "";
        Exception exception = null;
        try {
            //解析xml
            SAXReader reader = new SAXReader();
            Document document = reader.read(stream);
            Element root = document.getRootElement();
            Element filetype = root.element("filetype");
            List<Element> userlist = root.element("userlist").elements("user");
            if (filetype != null && filetype.getText().equals("user")) {
                for (Element user : userlist) {
                    SystemUserDO userDO = new SystemUserDO();
                    for (Field field : userDO.getClass().getDeclaredFields()) {
                        if (!Modifier.isStatic(field.getModifiers())) {
                            field.setAccessible(true);
                            Element filednode = user.element(field.getName());
                            field.set(userDO, BootUtil.convetXmlContent2FieldContent(filednode.getText(), field.getType()));
                        }
                    }
                    SystemUserDO dbinfo = service.selectOne(userDO.getRow_id());
                    if (dbinfo == null) {
                        insert(userDO);
                    } else {
                        update(userDO);
                    }
                }
            } else {
                errormsg = "导入文件不是人员文件！";
            }
        } catch (Exception e) {
            exception = e;
            errormsg = "导入失败";
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
        } finally {
            StringBuilder builder = new StringBuilder();
            if (StringUtil.isEmpty(errormsg)) {
                builder.append("导入人员成功！" + CommonUtil.getNewLine());
            } else {
                builder.append("导入人员失败！" + CommonUtil.getNewLine());
            }
            if (!StringUtil.isEmpty(errormsg)) {
                if (errormsg.equals("导入失败")) {
                    builder.append("失败异常信息:" + CommonUtil.getNewLine());
                    builder.append(exception.getMessage() + CommonUtil.getNewLine());
                    builder.append("失败堆栈信息:" + CommonUtil.getNewLine());
                    builder.append(exception.getStackTrace());
                } else {
                    builder.append("导入失败信息:" + errormsg + CommonUtil.getNewLine());
                }
            }
            LogUtil.writeLog("org/user", "log", builder.toString());
        }
        return errormsg;
    }
}
